/*-------------------------------------------------------------------------
 *
 * toast_helper.h
 *	  实现压缩或分离存储 varlena 属性的表 AM 的辅助函数。
 *
 * Copyright (c) 2000-2022, PostgreSQL Global Development Group
 *
 * src/include/access/toast_helper.h
 *
 *-------------------------------------------------------------------------
 */

#ifndef TOAST_HELPER_H
#define TOAST_HELPER_H

#include "utils/rel.h"

/*
 * 关于一个正在进行 toast 的元组列的信息。
 *
 * 注意：toast_action[i]可以具有以下值：
 *		' '						默认处理
 *		TYPSTORAGE_PLAIN		已处理 - 不要碰它
 *		TYPSTORAGE_EXTENDED	不可压缩，但可以移除
 *
 * 注意：toast_attr[i].tai_size 仅对 toast_action[i] 不同于 TYPSTORAGE_PLAIN 的 varlena 属性有效。
 */
typedef struct
{
	struct varlena *tai_oldexternal;
	int32		tai_size;
	uint8		tai_colflags;
	char		tai_compression;
} ToastAttrInfo;

/*
 * 关于一个正在进行 toast 的元组的信息。
 */
typedef struct
{
	/*
	 * 在调用 toast_tuple_init 之前，调用者必须初始化
	 * 以下字段。每个数组的长度必须等于
	 * ttc_rel->rd_att->natts。对于插入操作，tts_oldvalues 和 tts_oldisnull 字段
	 * 应该为 NULL。
	 */
	Relation	ttc_rel;		/* 包含元组的关系 */
	Datum	   *ttc_values;		/* 来自元组列的值 */
	bool	   *ttc_isnull;		/* 元组列的 null 标志 */
	Datum	   *ttc_oldvalues;	/* 来自上一个元组的值 */
	bool	   *ttc_oldisnull;	/* 来自先前元组的 null 标志 */

	/*
	 * 在调用 toast_tuple_init 之前，调用者应该将 tts_attr 设置为
	 * 指向长度等于 tts_rel->rd_att->natts 的 ToastAttrInfo 结构数组。
	 * 数组的内容不需要初始化。ttc_flags 也不需要初始化。
	 */
	uint8		ttc_flags;
	ToastAttrInfo *ttc_attr;
} ToastTupleContext;

/*
 * 指示 TOAST 操作总体状态的标志。
 *
 * TOAST_NEEDS_DELETE_OLD 表示需要删除一个或多个旧的 TOAST 数据项。
 *
 * TOAST_NEEDS_FREE 表示需要释放一个或多个 TOAST 值。
 *
 * TOAST_HAS_NULLS 表示在正在进行 toast 的元组中找到 null。
 *
 * TOAST_NEEDS_CHANGE 表示需要构建一个新元组；换句话说，toaster 做了某件事。
 */
#define TOAST_NEEDS_DELETE_OLD				0x0001
#define TOAST_NEEDS_FREE					0x0002
#define TOAST_HAS_NULLS						0x0004
#define TOAST_NEEDS_CHANGE					0x0008

/*
 * 指示与特定列相关的 TOAST 操作状态的标志。
 *
 * TOASTCOL_NEEDS_DELETE_OLD 表示需要删除此列的旧 TOAST 数据项。
 *
 * TOASTCOL_NEEDS_FREE 表示此列的值需要被释放。
 *
 * TOASTCOL_IGNORE 表示 toaster 不应进一步处理
 * 此列。
 *
 * TOASTCOL_INCOMPRESSIBLE 表示该列已被确认为不可压缩，但可以移除。
 */
#define TOASTCOL_NEEDS_DELETE_OLD			TOAST_NEEDS_DELETE_OLD
#define TOASTCOL_NEEDS_FREE					TOAST_NEEDS_FREE
#define TOASTCOL_IGNORE						0x0010
#define TOASTCOL_INCOMPRESSIBLE				0x0020

extern void toast_tuple_init(ToastTupleContext *ttc);
extern int	toast_tuple_find_biggest_attribute(ToastTupleContext *ttc,
											   bool for_compression,
											   bool check_main);
extern void toast_tuple_try_compression(ToastTupleContext *ttc, int attribute);
extern void toast_tuple_externalize(ToastTupleContext *ttc, int attribute,
									int options);
extern void toast_tuple_cleanup(ToastTupleContext *ttc);

extern void toast_delete_external(Relation rel, Datum *values, bool *isnull,
								  bool is_speculative);

#endif
